# TODO: Map save gamerule
# TODO: DeltaTime max check
# TODO: Screen RESIZE step sound

import pygame
from pygame.locals import *
import os
import json
from math import floor, ceil
from random import randint
from time import time
import threading

pygame.init()
pygame.mixer.init()
pygame.font.init()

NowPath = os.getcwd()
try:
    with open("StartSettings.json", encoding='UTF-8') as StartSettings:
        settings = json.load(StartSettings)
except FileNotFoundError:
    print("File \"Startsettings.json\" not found :(")
    quit()
Infos = pygame.display.Info()
if settings["FULLSCREEN"]:
    settings["WIDTH"], settings["HEIGHT"] = Infos.current_w, Infos.current_h

MouseX, MouseY = 0, 0
clock = pygame.time.Clock()
FGH = "---------------------"
key_pressed = pygame.key.get_pressed()
NowFPS = 60
inputting = False
command = ""
playing = True
loading = False
IFMshowwing = True
DeltaTime = 60
indicateCount = 0
LoadMapOvered = False
LoadFlag = False
Loadded = False
LoaddedName = ""
SaveMapName = ""
IFMwords = ""

class file:
    # image loads
    player_head_img = os.path.join("./texture/player_head.png")
    block_img = os.path.join("./texture/stone.png")
    indicate_img = os.path.join("./texture/indicate.png")
    dirt_background = os.path.join("./texture/Dirt_background.png")

    # sound loads
    Place = tuple(pygame.mixer.Sound(f"./sound/place/Stone_dig{i}.ogg") for i in range(1, 5))
    Break = tuple(pygame.mixer.Sound(f"./sound/broken/Stone_dig{i}.ogg") for i in range(1, 5))
    Step = tuple(pygame.mixer.Sound(f"./sound/step/Stone_step{i}.ogg") for i in range(1, 5))
    Words = {
        "IFM": pygame.font.Font("./font/Regular.otf", 16),
        "SOUND": pygame.font.Font("./font/Regular.otf", 13),
        "LOAD": pygame.font.Font("./font/Regular.otf", 20),
        "CMD": pygame.font.Font("./font/Regular.otf", 13)
    }

print(FGH)
screen = pygame.display.set_mode((settings["WIDTH"], settings["HEIGHT"]), RESIZABLE)
pygame.display.set_caption("Minecraft*  Rungame beta v1.3.2")
pygame.display.set_icon(pygame.image.load(file.player_head_img))
screen.fill("#B0C4DE")

Blocks = {}
LoadIFM = {}
BlocksRect = []
player_sprite = pygame.sprite.Group()
block_sprites = pygame.sprite.Group()


def ReString(string, val, pos, pos2=-1) -> str:
    if pos2 == -1: pos2 = pos
    tmp = list(string)
    for j in range(pos,pos2+1):
        tmp[j] = val[j-pos]
    return ''.join(tmp)

def int_to_bytes(num):
    temp_str = bin(num).replace("0b", "")
    if temp_str[0] == '-':
        signed = '1'
        temp_str = temp_str[1:]
    else:
        signed = '0'
    temp_str = '0' * (31-len(temp_str)) + temp_str
    temp_str = signed + temp_str
    temp_ls = [flag=='1' for flag in temp_str]
    ttple = []
    for i in range(4):
        t = temp_ls[i*8:i*8+8]
        temp_num = 0
        for j in range(8):
            temp_num = temp_num << 1 | t[j]
        ttple.append(temp_num)
    return bytes(ttple)

def bytes_to_int(byte):
    signed = bool(byte[0] & (1 << 7))
    temp_byte0 = byte[0] & ((1 << 7) - 1)
    tmp = [temp_byte0]
    for i in range(1,4):
        tmp.append(byte[i])
    res = 0
    for i in tmp:
        res = (res << 8) | i
    if signed:
        res = -res
    return int(res)

def RectNext(Rect1, Rect2) -> bool:
    if (
            Rect1.right == Rect2.left
            and Rect1.top < Rect2.bottom
            and Rect1.bottom > Rect2.top
    ):
        return True
    if (
            Rect1.left == Rect2.right
            and Rect1.top < Rect2.bottom
            and Rect1.bottom > Rect2.top
    ):
        return True
    if (
            Rect1.bottom == Rect2.top
            and Rect1.left < Rect2.right
            and Rect1.right > Rect2.left
    ):
        return True
    if (
            Rect1.top == Rect2.bottom
            and Rect1.left < Rect2.right
            and Rect1.right > Rect2.left
    ):
        return True
    return False


def getIFM() -> tuple:
    return (
            "Block: %d %d" % (round(player.PosX), round(player.PosY)),
            "X: %.2lf  Y: %.2lf" % (player.PosX, player.PosY),
            "Jumping: %d" % (player.jumping),
            "Suspenstion: %d" % (player.suspension),
            "NowFPS: %d  MaxFPS: %d" % (NowFPS, settings["MAXFPS"]),
            "Speed: %.2lfm/s" % (player.NowSpeed),
            "Display: %dx%d" % (settings["WIDTH"], settings["HEIGHT"])
        )


SoundList: list = []
class GSound:
    def __init__(self, Type: str, way: str):
        global SoundList
        self.type = Type
        self.way = way
        self.StartTime = time()
        self.NowTime = self.StartTime
        for i in range(len(SoundList)):
            if SoundList[i].type == self.type:
                SoundList[i].StartTime = self.NowTime
                SoundList[i].way = self.way
                del self
                return
        SoundList.append(self)

    def update(self) -> None:
        self.NowTime = time()
        if self.NowTime - self.StartTime > 1:
            SoundList.remove(self)
            del self
            return

class Fonts(object):
    def ShowLoading() -> None:
        DirtBg = pygame.transform.scale(dirt_bg, (settings["WIDTH"], settings["HEIGHT"]));
        screen.blit(DirtBg, (0, 0))
        LoadingWord = file.Words["LOAD"].render("Loading...", True, "white")
        LoadingRect = LoadingWord.get_rect()
        screen.blit(LoadingWord, ((settings["WIDTH"]-LoadingRect.w) / 2,
                                (settings["HEIGHT"]-LoadingRect.h) / 2))
    def ShowInformation() -> None:
        IFMwords: tuple = getIFM()
        XPOS: int = 10
        YPOS: int = 7
        for i, line in enumerate(IFMwords):
            word: pygame.Surface = file.Words["IFM"].render(line, True, "black")
            screen.blit(word, (XPOS, YPOS + i * 19))

    def ShowSounds() -> None:
        SoundLength = len(SoundList)
        for i in range(SoundLength):
            way = SoundList[SoundLength-i-1].way
            SoundWord = SoundList[SoundLength-i-1].type.center(20)
            if way == "left":
                SoundWord = ReString(SoundWord, "<-", 2, 3)
            elif way == "right":
                SoundWord = ReString(SoundWord, "->", 14, 15)
            word = file.Words["SOUND"].render(SoundWord, True, "black")
            screen.blit(word, (settings["WIDTH"]-120, settings["HEIGHT"]-20-SoundLength*18 + i*18))
            SoundList[SoundLength-i-1].update()

    def ShowCommand():
        word = file.Words["CMD"].render(command, True, "black")
        screen.blit(word, (30, settings["HEIGHT"]-50))


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load(file.player_head_img).convert()
        self.rect = self.image.get_rect()
        self.rect.center = (settings["WIDTH"] / 2, settings["HEIGHT"] / 2)
        self.SPEED = 500
        self.speed = self.SPEED * DeltaTime
        self.y_speed = 0
        self.gravity = 3000
        self.strenght = -1000
        self.tick = 0
        self.ticks = floor(self.speed * 2.5)
        self.LastX = self.LastY = 0
        self.jumping = self.LastJumping = False
        self.suspension = self.LastSuspension = True
        self.resur = (450, 300)
        self.RectX, self.RectY = (0, 300)
        self.PosX, self.PosY = (self.RectX / 50, self.RectY / 50)
        self.RollX, self.RollY = (self.RectX, self.RectY)
        self.ResurBool = True
        self.ResurHigh = 30
        self.NowSpeed = 0
        self.DiedCount = 0
        self.IsIntX = True
        self.IsIntY = True
        self.RePositioning = False

    def TouchBlock(self) -> bool:
        global BlocksRect
        for block in BlocksRect:
            if self.rect.colliderect(block):
                return True
        return False

    def positioning(self) -> None:
        self.rect.centerx = self.RectX - self.RollX + settings["WIDTH"] / 2
        self.rect.centery = self.RectY - self.RollY + settings["HEIGHT"] / 2

    def horizontal(self, x_speed) -> None:
        self.RectX += x_speed
        self.positioning()
        while self.TouchBlock():
            if x_speed > 0:
                self.RectX -= 1
            else:
                self.RectX += 1
            self.positioning()

    def vertical(self, Yspeed) -> None:
        if not self.TouchBlock():
            self.RectY += round(Yspeed * DeltaTime)
            self.positioning()
        while self.TouchBlock():
            if Yspeed > 0:
                self.RectY -= 1
                self.jumping = False
            else:
                self.RectY += 1
            self.positioning()
            self.y_speed = 0

    def died(self):
        self.DiedCount += 1
        print("YOU DIED x%d" % self.DiedCount)
        self.SetPos(self.resur[0] / 50, self.resur[1] / 50)

    def noise(self) -> None:
        global SoundWords, key_pressed
        self.tick += 3 * DeltaTime
        for block in BlocksRect:
            if RectNext(self.rect, block) and self.rect.bottom == block.top:
                if self.RectX != self.LastX:
                    if self.tick >= self.ticks:
                        self.tick = 0
                        file.Step[randint(0, 3)].play()
                        way = ""
                        if key_pressed[pygame.K_a]: way = "right"
                        else: way = "left"
                        GSound("STEP", way)
                        break

    def IsSuspension(self) -> bool:
        for block in BlocksRect:
            if RectNext(self.rect, block) and self.rect.bottom == block.top:
                return False
        return True

    def SetPos(self, pos_x, pos_y) -> None:
        self.PosX = pos_x
        self.PosY = pos_y
        self.RectX = self.LastX = int(pos_x * 50)
        self.RectY = self.LastY = int(pos_y * 50)
        self.suspension = self.LastSuspension = False
        self.jumping = self.LastJumping = False
        self.tick = 0
        self.y_speed = 0
        

    def CompSpeed(self) -> None:
        global NowTime
        TempTime = time()
        TimeSub = TempTime - NowTime
        if TimeSub == 0:
            TimeSub = 1
        self.NowSpeed = abs(self.LastX - self.RectX) * (1 / TimeSub) / 50
        NowTime = TempTime

    def update(self):
        global DiedCount, SoundWordsm, key_pressed
        # data update
        if self.y_speed * DeltaTime * DeltaTime >= 50:
            self.y_speed = 50 / DeltaTime / DeltaTime 
        self.suspension = self.IsSuspension()
        self.PosX = self.RectX / 50
        self.PosY = self.RectY / 50
        self.speed = ceil(self.SPEED * DeltaTime)
        self.IsIntX = not(self.RectX % 50)
        self.IsIntY = not(self.RectY % 50)
        self.ticks = self.SPEED / 500
        self.positioning()
        
        # keys check
        if not inputting and not loading:
            if key_pressed[pygame.K_a] and not key_pressed[pygame.K_d]:
                self.horizontal(-self.speed)
                self.noise()
            elif key_pressed[pygame.K_d] and not key_pressed[pygame.K_a]:
                self.horizontal(self.speed)
                self.noise()
            else:
                self.tick = self.ticks

            if key_pressed[pygame.K_w]:
                if not self.suspension:
                    self.y_speed = self.strenght
                    self.jumping = True

        
        self.y_speed += self.gravity * DeltaTime
        self.vertical(self.y_speed)
        self.RollX = self.RectX
        self.RollY = self.RectY
        self.positioning()
        self.CompSpeed()

        if self.ResurBool:
            if self.PosY > self.ResurHigh:
                self.died()
        if not self.suspension and self.LastSuspension:
            self.tick = 0
            file.Step[randint(0, 3)].play()
            if key_pressed[pygame.K_a]:way = "right"
            elif key_pressed[pygame.K_d]:way = "left"
            else: way = "mid"
            GSound("STEP", way)



player: Player = Player()

player_sprite.add(player)


class Block(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load(file.block_img).convert()
        self.XPos, self.YPos = (x, y)
        self.RectX = self.YPos * 50
        self.RectY = self.XPos * 50
        self.rect = self.image.get_rect()
        self.rect.centerx = self.XPos * 50 - player.RollX + settings["WIDTH"] / 2
        self.rect.centery = self.YPos * 50 - player.RollY + settings["HEIGHT"] / 2
        Blocks[(self.XPos, self.YPos)] = True
        block_sprites.add(self)
        BlocksRect.append(self.rect)

    def positioning(self) -> None:
        self.rect.centerx = self.XPos * 50 - player.RollX + settings["WIDTH"] / 2
        self.rect.centery = self.YPos * 50 - player.RollY + settings["HEIGHT"] / 2

    def InScreenCamere(self) -> bool:
        if self.rect.bottom < 0:
            return False
        if self.rect.top > settings["HEIGHT"]:
            return False
        if self.rect.right < 0:
            return False
        if self.rect.left > settings["WIDTH"]:
            return False
        return True

    def update(self):
        self.positioning()
        if Blocks[(self.XPos, self.YPos)] == 0:
            del Blocks[(self.XPos, self.YPos)]
            block_sprites.remove(self)
            BlocksRect.remove(self)
            self.kill()
            del self

def DrawBlocks():
    for block in block_sprites:
        screen.blit(block.image, block.rect.topleft)

class indicate(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load(file.indicate_img).convert()
        self.image.set_colorkey("white")
        self.rect = self.image.get_rect()
        self.MousePosX = MouseX + player.RollX - settings["WIDTH"] / 2
        self.MousePosY = MouseY + player.RollY - settings["HEIGHT"] / 2
        self.PosX = floor(self.MousePosX / 50)
        self.PosY = floor(self.MousePosY / 50)

    def postioning(self) -> None:
        self.MousePosX = MouseX + player.RollX - settings["WIDTH"] / 2 + 25
        self.MousePosY = MouseY + player.RollY - settings["HEIGHT"] / 2 + 25
        self.PosX = floor(self.MousePosX / 50)
        self.PosY = floor(self.MousePosY / 50)
        self.rect.centerx = self.PosX * 50 - player.RollX + settings["WIDTH"] / 2
        self.rect.centery = self.PosY * 50 - player.RollY + settings["HEIGHT"] / 2

    def update(self):
        global inputting
        if not inputting:
            self.postioning()
        if MouseX <= 1 or MouseX >= settings["WIDTH"] - 1 or MouseY <= 1 or MouseY >= settings["HEIGHT"] - 1 or inputting:
            self.image.set_alpha(0)
        else:
            self.image.set_alpha(255)


def BuildBlock(XPos, YPos) -> None:
    global Blocks
    if (XPos, YPos) not in Blocks:
        Block(XPos, YPos)


def RemoveBlock(XPos, YPos) -> None:
    global Blocks
    if (XPos, YPos) in Blocks:
        Blocks[(XPos, YPos)] = False


def RunCommand(command) -> None:
    global Blocks, loading, LoadFlag, LoaddedName, SaveMapName
    if len(command) == 0:
        return
    if command[0] == "gamerule":
        rule = command[1]
        if rule == "ResurPos":
            xx = command[2]
            yy = command[3]
            if xx == '~':
                xx = player.RectX
            else:
                xx = int(xx * 50)
            if yy == '~':
                yy = player.RectY
            else:
                yy = int(yy * 50)
            player.resur = (xx, yy)
        elif rule == "PlayerSpeed":
            spd = int(command[2])
            player.SPEED = spd
        elif rule == "PlayerGravity":
            gravity = command[2]
            strenght = command[3]
            if gravity == "~":
                gravity = player.gravity
            else:
                gravity = int(gravity)
            if strenght == "~":
                strenght = player.strenght
            else:
                strenght = int(strenght)
            player.gravity = gravity
            player.strenght = strenght
        elif rule == "ResurCheck":
            Boolean = eval(command[2])
            player.ResurBool = Boolean
            if Boolean:
                high = command[3]
                if high == '~':
                    player.ResurHigh = player.PosY
                else:
                    player.ResurHigh = int(high)
        else:
            print("No gamerule named \"", rule, "\"")
    elif command[0] == "setting":
        sett: str = command[1]
        if sett == "MaxFPS":
            CheckFPS = float(command[2])
            if command[2] == "inf":
                CheckFPS = 2147483647
            else:
                CheckFPS = int(CheckFPS)
            if CheckFPS < 10:
                print("FPS too small! :(")
                return
            settings["MAXFPS"] = CheckFPS
    elif command[0] == "setblock":
        block = command[3]
        xx = command[1]
        yy = command[2]
        if xx == '~': xx = round(player.PosX)
        else: xx = int(xx)
        if yy == '~': yy = round(player.PosY)
        else: yy = int(yy)
        if block == "stone":
            BuildBlock(xx, yy)
        elif block == "air":
            RemoveBlock(xx, yy)
    elif command[0] == "fill":
        try:
            x1 = command[1]
            y1 = command[2]
            x2 = command[3]
            y2 = command[4]
        except:
            print("Missing parameters :(")
        try:
            if x1 == '~': x1 = round(player.PosX)
            else: x1 = int(x1)
            if y1 == '~': y1 = round(player.PosY)
            else: y1 = int(y1)
            if x2 == '~': x2 = round(player.PosX)
            else: x2 = int(x2)
            if y2 == '~': y2 = round(player.PosY)
            else: y2 = int(y2)
        except:
            print("Wrong position :(")
        if x1 > x2:
            x1, x2 = (x2, x1)
        if y1 > y2:
            y1, y2 = (y2, y1)
        block = command[5]
        for i in range(x1, x2 + 1):
            for j in range(y1, y2 + 1):
                if block == "stone":
                    BuildBlock(i, j)
                elif block == "air":
                    RemoveBlock(i, j)
        print("Fill block Successful")
    elif command[0] == "kill":
        player.died()
    elif command[0] == "tp":
        try:
            xx = command[1]
            yy = command[2]
            if xx == "~":
                xx = player.PosX
            else:
                xx = float(xx)
            if yy == "~":
                yy = player.PosY
            else:
                yy = float(yy)
            player.SetPos(xx, yy)
        except:
            print("Wrong position :(")
    elif command[0] == "save":
        if Loadded and len(command) == 1:
            SaveMapName = LoaddedName
        else:
            SaveMapName = command[1]
        SaveThread = threading.Thread(target=SaveMap)
        SaveThread.start()
    elif command[0] == "loadmap":
        LoaddedName = command[1]
        loading = True
        LoadFlag = True
    elif command[0] == "mapls":
        Maps = [mp for mp in os.listdir(NowPath + "/saves") if os.path.isdir(os.path.join(NowPath + "/saves", mp))]
        print("MAP:")
        for mp in Maps:
            print(mp)
    elif command[0] == "exit" or command[0] == "quit":
        playing = False
    else:
        print("No command named \"{}\" :(".format(command[0]))

Inputthing = ''
def InputCommand(events) -> None:
    global key_pressed, command, Inputtick, Inputthing
    for event in events:
        if event.type == pygame.KEYDOWN:
            if key_pressed[pygame.K_BACKSPACE] and command:
                command = command[:-1]
            else:
                Inputthing = event.unicode
                command += Inputthing


RunCommand(["fill", "-20", "11", "20", "16", "stone"])
indicateGroup = pygame.sprite.Group()
indicate = indicate()
indicateGroup.add(indicate)
dirt_bg = pygame.image.load(file.dirt_background)
TempFlag = False
NowTime = time()

def SaveMap() -> None:
    global SaveMapName
    MapPath = "./saves/" + SaveMapName
    if not os.path.isdir(MapPath):
        os.mkdir(MapPath)
    ChunkFile = open(MapPath + "/chunk.dat", "wb")
    for block in Blocks:
        ChunkFile.write(int_to_bytes(block[0]))
        ChunkFile.write(int_to_bytes(block[1]))
    ChunkFile.close()
    PlyPath = MapPath + "/ply"
    if not os.path.isdir(PlyPath):
        os.mkdir(PlyPath)
    PlyFile = open(PlyPath + "/nowinf", "wb")
    PlyFile.write(int_to_bytes(player.RectX))
    PlyFile.write(int_to_bytes(player.RectY))
    PlyFile.close()
    RulePath = MapPath + "/rule"
    if not os.path.isdir(RulePath):
        os.mkdir(RulePath)
    GameRuleFile = open(RulePath + "/gamerule", "wb")
    GameRuleFile.write(int_to_bytes(int(player.ResurBool)))
    GameRuleFile.write(int_to_bytes(player.ResurHigh))
    GameRuleFile.write(int_to_bytes(player.resur[0]))
    GameRuleFile.write(int_to_bytes(player.resur[1]))
    print("Save map Successful :)")

def LoadMap() -> None:
    global LoaddedName, LoadIFM, block_sprites, DiedCount, \
           loading, LoadMapOvered, BlocksRect, Blocks, \
           Loadded
    if not LoadMapOvered:
        for k in (0,):
            if not os.path.exists("./saves/" + LoaddedName + "/chunk.dat") :
                print("Chunk data lost :(")
                break
            try:
                Fonts.ShowLoading()
                block_sprites.empty()
                BlocksRect = []
                Blocks = {}
                MapFile = open("./saves/" + LoaddedName + "/chunk.dat", "rb+")
                ChunkX = MapFile.read(4)
                ChunkY = MapFile.read(4)
                while ChunkX and ChunkY:
                    POSX = bytes_to_int(ChunkX)
                    POSY = bytes_to_int(ChunkY)
                    Block(POSX, POSY)
                    ChunkX = MapFile.read(4)
                    ChunkY = MapFile.read(4)
                Loadded = True
                MapFile.close()
                PlyFile = open("./saves/" + LoaddedName + "/ply/nowinf", "rb+")
                POSX = bytes_to_int(PlyFile.read(4)) / 50
                POSY = bytes_to_int(PlyFile.read(4)) / 50
                player.SetPos(POSX, POSY)
                PlyFile.close()
                GameRuleFile = open("./saves/" + LoaddedName + "/rule/gamerule", "rb+")
                player.ResurBool = bool(bytes_to_int(GameRuleFile.read(4)))
                player.ResurHigh = bytes_to_int(GameRuleFile.read(4))
                player.resur = (bytes_to_int(GameRuleFile.read(4)), bytes_to_int(GameRuleFile.read(4)))
                GameRuleFile.close()
                print("Load map Successful :)")
            except:
                print("Failed to load world :(")
        loading = False
        LoadMapOvered = True
        LoadIFM = {}



def Resize(isfullscreen):
    global screen, settings
    for event in pygame.event.get(VIDEORESIZE):
        size = settings["WIDTH"], settings["HEIGHT"] = event.size[0], event.size[1]
        screen = pygame.display.set_mode((settings["WIDTH"], settings["HEIGHT"]), RESIZABLE)
    for event in pygame.event.get(KEYDOWN):
        if event.key == K_F11:
            if isfullscreen:
                isfullscreen = False
                SIZE = settings["WIDTH"], settings["HEIGHT"] = (settings["LASTW"], settings["LASTH"])
                screen = pygame.display.set_mode((settings["WIDTH"], settings["HEIGHT"]), RESIZABLE)
            else:
                isfullscreen = True
                SIZE = settings["WIDTH"], settings["HEIGHT"] =  pygame.display.list_modes()[0]
                screen = pygame.display.set_mode(SIZE, FULLSCREEN)
        pygame.event.post(event)
    return isfullscreen

while playing:
    DeltaTime = clock.tick(settings["MAXFPS"]) / 1000.0
    if DeltaTime > 0.1:
        continue
    indicateCount += 1
    indicateCount %= 10000
    NowFPS = clock.get_fps()
    KeyDown = False
    settings["FULLSCREEN"] = Resize(settings["FULLSCREEN"])
    if not settings["FULLSCREEN"]:
        settings["LASTW"], settings["LASTH"] = settings["WIDTH"], settings["HEIGHT"]
    MouseX, MouseY = pygame.mouse.get_pos()
    events = pygame.event.get()
    key_pressed = pygame.key.get_pressed()
    for event in events:
        if event.type == pygame.QUIT:
            playing = False
            break
        elif event.type == pygame.MOUSEBUTTONDOWN:
            MousePressed = pygame.mouse.get_pressed()
            if 0 <= MouseX <= settings["WIDTH"] and 0 <= MouseY <= settings["HEIGHT"] and not inputting:
                PosX, PosY = (indicate.PosX, indicate.PosY)
                way = ""
                if PosX > player.PosX:way = "right"
                elif PosX < player.PosX:way = "left"
                else: way = "mid"
                if (PosX, PosY) not in Blocks and MousePressed[2]:
                    ColliderLeft = (player.RectX) // 50
                    ColliderRight = (player.RectX + 50 - 1) // 50
                    ColliderUp = (player.RectY) // 50
                    ColliderDown = (player.RectY + 50 - 1) // 50
                    if not (
                            (PosX == ColliderLeft and PosY == ColliderUp)
                            or (PosX == ColliderRight and PosY == ColliderUp)
                            or (PosX == ColliderLeft and PosY == ColliderDown)
                            or (PosX == ColliderRight and PosY == ColliderDown)
                    ):
                        BuildBlock(PosX, PosY)
                        file.Place[randint(0, 3)].play()
                        GSound("PLACE", way)
                elif (PosX, PosY) in Blocks and MousePressed[0]:
                    RemoveBlock(PosX, PosY)
                    file.Break[randint(0, 3)].play()
                    GSound("BREAK", way)
        elif event.type == pygame.KEYDOWN:
            if key_pressed[pygame.K_F3]:
                IFMshowwing = not IFMshowwing
            if key_pressed[pygame.K_SLASH] and not inputting:
                inputting = True
                command = ""
            if key_pressed[pygame.K_ESCAPE]:
                if inputting:
                    inputting = False
                    command = ""
                else:
                    playing = False
            if key_pressed[pygame.K_t] and not inputting:
                inputting = True
                command = ""
                TempFlag = True
            if key_pressed[pygame.K_RETURN]:
                if inputting:
                    inputting = False
                    if command[0] == '/':
                        # try:
                        command = command[1:]
                        RunCommand(command.split())
                        # except:
                        #     print("Error RunCommand return -1")
                    command = ""


    if loading and LoadFlag:
        LoadThread = threading.Thread(target=LoadMap)
        LoadThread.start()
        LoadFlag = False
    elif not loading:
        screen.fill("#B0C4DE")
        block_sprites.update()
        player_sprite.update()
        indicateGroup.update()
        player_sprite.draw(screen)
        DrawBlocks()
        indicateGroup.draw(screen)
        Fonts.ShowSounds()
        if IFMshowwing:
            Fonts.ShowInformation()
    if not LoadMapOvered and loading:
        Fonts.ShowLoading()
    if not loading and LoadMapOvered:
        LoadMapOvered = False
    if inputting:
        InputCommand(events)
        if TempFlag:
            command = ""
            TempFlag = False
        Fonts.ShowCommand()
    player.LastX, player.LastY = (player.RectX, player.RectY)
    player.LastJumping = player.jumping
    player.LastSuspension = player.suspension
    pygame.display.update()

pygame.quit()

def RebackSettings():
    global settings
    settings["FULLSCREEN"] = False
    settings["WIDTH"] = 900
    settings["HEIGHT"] = 600
    settings["MAXFPS"] = 60

StartSettingsWrite = open("StartSettings.json", "w")
StartSettingsWrite.write(json.dumps(settings))

print("Game Over!")
